package nr.co.mhgames.polyanim.util;

import java.util.Locale;

/**
 * Basic 2d vector class. It's all public to allow convenient access.
 * 
 * @author Mika Halttunen
 */
public class Vector2f implements Cloneable {
	/** X component */
	public float x;

	/** Y component */
	public float y;

	/** Zero vector */
	public static final Vector2f ZERO = new Vector2f(0, 0);

	/** Unit vector */
	public static final Vector2f UNIT = new Vector2f(1, 1);


	public Vector2f() {
		x = y = 0;
	}

	public Vector2f(float v) {
		x = y = v;
	}

	public Vector2f(float x_, float y_) {
		x = x_;
		y = y_;
	}

	public Vector2f(float v[]) {
		assert v.length >= 2;
		x = v[0];
		y = v[1];
	}

	public Vector2f(Vector2f v) {
		x = v.x;
		y = v.y;
	}

	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Float.floatToIntBits(x);
		result = prime * result + Float.floatToIntBits(y);
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Vector2f))
			return false;

		Vector2f other = (Vector2f) obj;
		if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x))
			return false;

		if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y))
			return false;

		return true;
	}

	public void add(Vector2f v) {
		x += v.x;
		y += v.y;
	}

	public void add(float x_, float y_) {
		x += x_;
		y += y_;
	}

	public static Vector2f add(Vector2f a, Vector2f b) {
		return new Vector2f(a.x + b.x, a.y + b.y);
	}

	public void sub(Vector2f v) {
		x -= v.x;
		y -= v.y;
	}

	public void sub(float x_, float y_) {
		x -= x_;
		y -= y_;
	}

	public static Vector2f sub(Vector2f a, Vector2f b) {
		return new Vector2f(a.x - b.x, a.y - b.y);
	}

	public void mul(Vector2f v) {
		x *= v.x;
		y *= v.y;
	}

	public void mul(float x_, float y_) {
		x *= x_;
		y *= y_;
	}

	public static Vector2f mul(Vector2f a, Vector2f b) {
		return new Vector2f(a.x * b.x, a.y * b.y);
	}

	public void div(Vector2f v) {
		x /= v.x;
		y /= v.y;
	}

	public void div(float x_, float y_) {
		x /= x_;
		y /= y_;
	}

	public static Vector2f div(Vector2f a, Vector2f b) {
		return new Vector2f(a.x / b.x, a.y / b.y);
	}

	@Override
	public String toString() {
		return String.format((Locale) null, "Vector2f: (%f, %f), %s", x, y, super.toString());
	}


	/**
	 * Dot product with another vector.
	 * 
	 * @param v
	 *            Vector
	 * @return The dot product
	 */
	public float dot(Vector2f v) {
		return x * v.x + y * v.y;
	}

	/**
	 * Normalize the vector. The original length prior the normalization is
	 * returned.
	 * 
	 * @return Original vector length
	 */
	public float normalize() {
		float len = (float) Math.sqrt(x * x + y * y);
		x /= len;
		y /= len;
		return len;
	}

	/**
	 * Return the vector length.
	 * 
	 * @return Vector length
	 */
	public float length() {
		return (float) Math.sqrt(x * x + y * y);
	}

	/**
	 * Return the vector length squared. Use of this method is preferred over
	 * {@link #length()}, if possible, as this avoids the somewhat costly square
	 * root operation.
	 * 
	 * @return Vector length squared
	 */
	public float lengthSquared() {
		return x * x + y * y;
	}

	/**
	 * Set the vector length to the given value.
	 * 
	 * @param len
	 *            Desired length
	 */
	public void setLength(float len) {
		float l = length();
		x *= len / l;
		y *= len / l;
	}

}
